﻿package Core  
{	
	import com.junkbyte.console.Cc;
	
	import Network.TCPClient;
	import Network.TCPConstants;
	import Network.DataMessage;
	import Network.TCPMessageEvent;
	
	import Gameplay.BonusInfo;
	
	import flash.events.EventDispatcher;
	import flash.events.Event;	
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	
	public class TCPGameClient extends EventDispatcher
	{
		private var FGame:Game;
		private var FClient:TCPClient;
		private var FMessage:DataMessage;
		
		public function TCPGameClient(AGame:Game):void
		{
			FGame = AGame;			
			FClient = new TCPClient(FGame);
			FClient.addEventListener(Event.CONNECT, SendHandshake);			
			FClient.addEventListener(IOErrorEvent.IO_ERROR, OnIOError);
			FClient.addEventListener(SecurityErrorEvent.SECURITY_ERROR, OnSecurityError);
			FClient.addEventListener(TCPConstants.NEW_CLIENT, OnNewClient);
			FClient.addEventListener(TCPConstants.CONNECTION_REJECTED, OnConnectionReject);
			FClient.addEventListener(TCPConstants.NEW_BATTLE, OnNewBattle);
			FClient.addEventListener(TCPConstants.REMOVE_BATTLE, OnRemoveBattle);
			FClient.addEventListener(TCPConstants.BATTLES_LIST, OnBattlesList);
			FClient.addEventListener(TCPConstants.ACCEPT_BATTLE, OnBattlesAccept);
			FClient.addEventListener(TCPConstants.BEAT, OnBeat);
			FClient.addEventListener(TCPConstants.CLIENT_EXIT, OnClientExit);
			FClient.addEventListener(Event.CLOSE, OnDisconnect);
		}
		
		public function Connect():void
		{
			FClient.Connect();
		}
		
		public function AddTCPListener(AType:String, ADelegate:Function):void
		{
			FClient.addEventListener(AType, ADelegate);
		}
		
		public function RemoveTCPListener(AType:String, ADelegate:Function):void
		{
			FClient.removeEventListener(AType, ADelegate);
		}
		
		private function SendHandshake(e:Event):void
		{
			FMessage = new DataMessage();			
			FMessage.Message = FGame.UserID;
			FMessage.DataType = TCPConstants.ID_NewClient;
			FClient.Send(FMessage);
		}
		
		public function SendNewBattle(ATrackID:int):void
		{
			FMessage = new DataMessage();
			FMessage.Message = FGame.UserID + ',' + FGame.User.Name;
			FMessage.Index = ATrackID;
			FMessage.Points = int(FGame.User.Rating);
			FMessage.DataType = TCPConstants.ID_NewBattle;
			FClient.Send(FMessage);
		}
		
		public function SendRemoveBattle():void
		{
			FMessage = new DataMessage();
			FMessage.Message = FGame.UserID;
			FMessage.DataType = TCPConstants.ID_RemoveBattle;
			FClient.Send(FMessage);
		}
		
		public function SendBattlesListRequest():void
		{
			FMessage = new DataMessage();
			FMessage.DataType = TCPConstants.ID_BattlesListRequest;
			FClient.Send(FMessage);
		}
		
		public function SendBattleAccept(ATrack:int, AUID:String):void
		{
			FMessage = new DataMessage();
			FMessage.DataType = TCPConstants.ID_AcceptBattle;
			FMessage.Message = AUID;
			FMessage.Index = ATrack;
			FClient.Send(FMessage);
		}
		
		public function SendBeat(AInfo:BonusInfo):void
		{
			FMessage = new DataMessage();
			FMessage.DataType = TCPConstants.ID_Beat;
			FMessage.Index = AInfo.ID;
			FMessage.Points = AInfo.Points;
			FMessage.Message = AInfo.BonusType + ',' + AInfo.BonusPoints;
			FClient.Send(FMessage);
		}
		
		private function OnNewClient(e:TCPMessageEvent):void
		{
			if(e.Message.Message == FGame.UserID)			
				dispatchEvent(new Event(Event.CONNECT));
		}
		
		private function OnNewBattle(e:TCPMessageEvent):void
		{
			FGame.Battles.AddBattle(e.Message);
		}
		
		private function OnRemoveBattle(e:TCPMessageEvent):void
		{
			FGame.Battles.RemoveBattle(e.Message.Message);
		}
		
		private function OnBattlesList(e:TCPMessageEvent):void
		{
			FGame.Battles.BattlesList = e.Message.Message;
		}
		
		private function OnBattlesAccept(e:TCPMessageEvent):void
		{
			Cc.log('Battle accepted by: ' + e.Message.Message);
			Cc.log('Battle accepted on track: ' + e.Message.Index);
			SendRemoveBattle();
			FGame.StartBattle(e.Message.Index, e.Message.Message);
		}		
		
		private function OnBeat(e:TCPMessageEvent):void
		{
			FGame.Gameplay.OnExternalBeat(e.Message);
		}		
		
		private function OnClientExit(e:TCPMessageEvent):void
		{			
			FGame.Battles.RemoveBattle(e.Message.Message);
		}	
		
		private function OnConnectionReject(e:TCPMessageEvent):void
		{
			FGame.ShowError('Игровой сервер оборвал подключение. Причина: ' + e.Message.Message);
			Cc.error('Connection rejected on reason: ' + e.Message.Message);
		}	
		
		private function OnDisconnect(e:Event):void
		{
			FGame.ShowError('Невозможно установить соединение с сервером по адресу: ' + 
							FGame.Settings.Host + '. Возможно, Вы уже открыли окно ' +
							'клиента на другой странице. Если это единственный ' +
							'открытый экземпляр игрового клиента - попробуйте перезагрузить страницу.');
			dispatchEvent(new Event(Event.CLOSE));
		}
		
		private function OnIOError(e:IOErrorEvent):void
		{
			FGame.ShowError('Ошибка при подключении к игровому серверу: ' + e.text);
		}
		
		private function OnSecurityError(e:SecurityErrorEvent):void
		{
			FGame.ShowError('Ошибка при подключении к игровому серверу: ' + e.text);
		}
	}	
}
